<template>
  <div class="select-tag-group">
    <a-select
      placeholder="请选择标签组"
      :value="tagGroupId"
      show-search
      option-filter-prop="label"
      style="width: 416px"
      :disabled="DmpSubTaskType.textSimilarity === subTaskType"
      :options="tagGroupList"
      @update:value="value => emits('update:tagGroupId', value)"
      @change="onTagGroupChange"
    />
    <a-button
      v-if="tagGroupId && subTaskType !== DmpSubTaskType.textSimilarity"
      type="link"
      class="ml-16"
      @click="showModal(tagGroupId, false)"
    >
      管理标签组
    </a-button>
  </div>

  <a-modal
    v-model:open="open"
    :title="modelTitle"
    destroy-on-close
    centered
    :ok-button-props="{ disabled: checkedKeys.checked.length === 0 }"
    :after-close="handleCancel"
    @ok="handleOk"
  >
    <div class="modal-body">
      <div class="tips">
        <i class="iconfont icon-information-fill"></i>
        <span>标注任务内的标签默认不存在层级关系，为保证标注结果的准确性，推荐使用最末级标签</span>
      </div>
      <g-input v-model:value="searchInputValue" placeholder="请输入关键词" allow-clear>
        <template #prefix><SearchOutlined /></template>
      </g-input>
      <div class="tools mt-8">
        <span>快捷选择</span>
        <a-button class="ml-20" type="link" @click="selectLastChild">最末级标签</a-button>
        <a-button class="ml-12" type="link" @click="selectAll">全选</a-button>
      </div>
      <div class="h-300 mt-8">
        <a-tree
          :key="tagGroupId"
          v-model:checkedKeys="checkedKeys"
          v-model:expanded-keys="expandedKeys"
          :selectable="false"
          :auto-expand-parent="true"
          :tree-data="treeData"
          :height="300"
          check-strictly
          checkable
          :virtual="false"
          @expand="onExpand"
        >
          <template #title="{ title }">
            <span v-if="title.indexOf(searchInputValue) > -1">
              {{ title.substring(0, title.indexOf(searchInputValue)) }}
              <span style="color: #f50">{{ searchInputValue }}</span>
              {{ title.substring(title.indexOf(searchInputValue) + searchInputValue.length) }}
            </span>
            <span v-else>{{ title }}</span>
          </template>
        </a-tree>
      </div>
    </div>
  </a-modal>
</template>

<script lang="ts" setup>
  import type { TreeProps } from 'ant-design-vue'
  import { Key } from 'ant-design-vue/es/_util/type'
  import { SelectValue } from 'ant-design-vue/es/select'
  import { DataNode } from 'ant-design-vue/es/tree'
  import { ref, watch } from 'vue'

  import { dmpTaskApi } from '@/services'

  import { DmpSubTaskType } from '../../types'

  export interface Props {
    tagGroupId: string | undefined
    // 标注任务子类型
    subTaskType: DmpSubTaskType
  }
  const props = withDefaults(defineProps<Props>(), {})
  const emits = defineEmits<{
    (e: 'update:tagGroupId', params: any): void
    (e: 'update:subTaskType', params: DmpSubTaskType): void
  }>()

  //  表单保存的数据，用于提交
  const saveTagGroupId = ref<string | undefined>(props.tagGroupId)

  const open = ref<boolean>(false)
  const modelTitle = ref('标签组名称')
  const tagGroupList = ref<{ label: string; value: string }[]>([])
  const searchInputValue = ref('')
  const selectedKeys = ref<(string | number)[]>([])
  let allTreeNodeList: any[] = []
  const expandedKeys = ref<(string | number)[]>([])
  const autoExpandParent = ref<boolean>(true)
  const treeData = ref<TreeProps['treeData']>([])
  const checkedKeys = ref<{ checked: (string | number)[] }>({
    checked: []
  })

  // 用户切换子任务类型时，清空选中的标签
  watch(
    () => props.subTaskType,
    subTaskType => {
      // 根据不同标注类型，设置默认标签组
      switch (subTaskType) {
        case DmpSubTaskType.textSimilarity:
          emits('update:tagGroupId', '1')
          tagGroupList.value.push({
            label: '文本相似度默认标签组',
            value: '1'
          })
          break
        default:
          emits('update:tagGroupId', undefined)
          saveTagGroupId.value = undefined
          tagGroupList.value = tagGroupList.value.filter(it => it.value !== '1')
          break
      }

      checkedKeys.value.checked = []
    },
    {
      immediate: true
    }
  )

  watch(searchInputValue, value => {
    const expanded = allTreeNodeList
      .map((item: TreeProps['treeData'][number]) => {
        if (item.title.indexOf(value) > -1) {
          return getParentKey(item.key, treeData.value)
        }
        return null
      })
      .filter((item, i, self) => item && self.indexOf(item) === i)
    expandedKeys.value = expanded as (string | number)[]

    autoExpandParent.value = true
  })

  const getTagGroupList = async () => {
    const { data } = await dmpTaskApi.tagGroupAllList()
    console.log('logo', data)
    tagGroupList.value = data.map((it: any) => ({
      label: it.name,
      value: it.id
    }))
  }

  const onTagGroupChange = async (selectValue: SelectValue) => {
    showModal(selectValue)
  }

  /** 将接口数据格式化为树形数据 */
  const recordsToTreeData = (records: any[]) => {
    return records.map((it: any) => {
      if (it.children) {
        it.children = recordsToTreeData(it.children)
      }
      allTreeNodeList.push({
        title: it.name,
        key: it.id
      })
      return {
        title: it.name,
        key: it.id,
        children: it.children
      }
    })
  }

  const getParentKey = (key: string | number, tree: TreeProps['treeData']): string | number | undefined => {
    let parentKey
    for (let i = 0; i < tree.length; i++) {
      const node = tree[i]
      if (node.children) {
        if (node.children.some(item => item.key === key)) {
          parentKey = node.key
        } else if (getParentKey(key, node.children)) {
          parentKey = getParentKey(key, node.children)
        }
      }
    }
    return parentKey
  }

  /**获取最末级标签 */
  const getLastChild = (tree: TreeProps['treeData']) => {
    return tree!.reduce((acc, cur) => {
      if (cur.children) {
        acc.push(...getLastChild(cur.children))
      } else {
        acc.push(cur.key)
      }
      return acc
    }, [])
  }
  /**选择最末级标签 */
  const selectLastChild = () => {
    checkedKeys.value.checked = getLastChild(treeData.value)
  }
  /**全选 */
  const selectAll = () => {
    checkedKeys.value.checked = allTreeNodeList.map(it => it.key) as string[]
  }

  /** 收起筛选项和其子项 */
  const clearExpandKeys = (node: DataNode) => {
    expandedKeys.value = expandedKeys.value.filter(key => key !== node.key)
    if (node.children) {
      node.children.forEach(child => {
        clearExpandKeys(child)
      })
    }
  }

  const onExpand = (keys: Key[], arg: any) => {
    autoExpandParent.value = false
    if (!arg.expanded) {
      clearExpandKeys(arg.node)
    }
  }

  const showModal = async (labelGroupId: SelectValue, init = true) => {
    open.value = true
    const { data } = await dmpTaskApi.tagList({
      offset: 1,
      limit: 999,
      labelGroupId
    })
    treeData.value = recordsToTreeData(data.records)

    // 如果是初始化，选择最末级标签
    if (init) {
      selectLastChild()
    } else {
      checkedKeys.value.checked = selectedKeys.value
    }
  }

  const handleOk = () => {
    saveTagGroupId.value = props.tagGroupId
    selectedKeys.value = checkedKeys.value.checked
    open.value = false
  }

  const handleCancel = () => {
    // 回退到上一次保存的状态
    emits('update:tagGroupId', saveTagGroupId.value)
    open.value = false
    searchInputValue.value = ''
    treeData.value = []
    checkedKeys.value.checked = []
    expandedKeys.value = []
    allTreeNodeList = []
  }

  /* init------------------------------------------------------------------------ */
  const init = async () => {
    getTagGroupList()
  }

  init()
  /* ------------------------------------------------------------------------ */
  defineExpose({
    selectedKeys
  })
</script>

<style lang="less" scoped>
  .select-tag-group {
    display: flex;
    align-items: center;
  }

  .modal-body {
    // padding: 16px;
    .tips {
      display: flex;
      align-items: flex-start;
      margin-bottom: 16px;
      font-size: 14px;
      color: #999;

      .iconfont {
        width: 12px;
        .font12();

        transform: translateY(1px);
        color: @text04;
      }

      span {
        margin-left: 8px;
        color: @text03;
        .font12();

        line-height: 20px;
      }
    }
  }
</style>
